/*
 * T.Raynal - A.Aviles - F.Diallo
 * XML-Scenarios
 * PPA AL5-2
 * December 2012 
 */
package model;

import java.io.Serializable;
import java.util.LinkedList;
import java.util.Queue;
import common.Commons.STATE;
import common.exception.EvaluationException;
import model.scenario.UnregisteredComponentException;
import model.serialization.XmlSerializable;
import model.serialization.XmlArray;
import model.serialization.XmlAttribute;
import model.serialization.XmlElement;
import model.serialization.XmlArray.ELEMENT;
import model.serialization.XmlArray.STRUCTURE;


// TODO: Auto-generated Javadoc
/**
 * Represent a Situation.
 */
@XmlElement(name = "SITUATION")
public class Situation  implements XmlSerializable, Serializable {


	private static final long serialVersionUID = 1L;

	/** The Label. */
	@XmlAttribute (name="name")
	public String Label;
	
	/** Alternatives of the situation */
	@XmlArray(name ="CASES", hasContainer=false, structure=STRUCTURE.QUEUE, type=ELEMENT.CASE) 
	public Queue<Case> Cases;
	
	/** Yield of the Situation */
	public String _result;
	

	private STATE _state;

	/**
	 * State of the situation.
	 *
	 * @return STATE
	 */
	public STATE state()
	{
		return _state;
	}
	
	/**
	 * Checks if is bottleneck: no alternative forkable.
	 *
	 * @return true, if is bottleneck
	 */
	public boolean isBottleneck()
	{
		boolean result = true;
		
		for (Case c : Cases) {
			if (!(c.state()==STATE.PROCEEDED))
			{
				result = false;
				break;
			}
		}
		return result;
	}
	
	/**
	 * Instantiates a new situation.
	 *
	 * @param Situation's name
	 */
	public Situation(String label)
	{
		Label = label;
		_result = null;
		_state = STATE.PENDING;
		Cases = new LinkedList<Case>();
	}
		
	/**
	 * Reset the situation.
	 */
	public void reset() {
		_result = null;
		_state= STATE.PENDING;
		
		for (Case c : Cases) {
			c.reset();
		}
	}

	/**
	 * Yield of the situation.
	 *
	 * @return String
	 */
	public String yield() {
		return _result;
	}

	/**
	 * Yield the next alternative to be evaluated.
	 *
	 * @return Case
	 * @throws EvaluationException
	 */
	public Case next() throws EvaluationException {
		
		Case result = null;
		
		if (Cases.size()==0)
			throw new EvaluationException("Empty case stack");
		
		for (Case c : Cases) {
			if (c.state()==STATE.PENDING)
			{
				result= c;
				break;
			}
		}
		
		return result;
	}
	
	/**
	 * Current alternative.
	 *
	 * @return Case
	 * @throws EvaluationException
	 */
	public Case current () throws EvaluationException
	{
		if (Cases.size()==0)
			throw new EvaluationException("Empty case stack");
		
		Case current = null;
		
		for (Case c : Cases) {
		if (c.state()!= STATE.PENDING){
			current =c;
			}
		}
		return current;
	}
	
	/**
	 * Eval.
	 *
	 * @return true, if successful
	 * @throws EvaluationException
	 */
	public boolean eval() throws EvaluationException
	{
		boolean result = false;
		
		if (result =next()
				.eval())
		{
			_state = STATE.PROCEEDED;
			_result = current().yield(); 
		}
		
		return result;
	}

	/**
	 * Add an alternative to the situation.
	 *
	 * @param Case
	 */
	public void put(Case value) {
		Cases.add(value);
	}

	/**
	 * Gets an alternative.
	 *
	 * @param Case's id
	 * @return Case
	 * @throws UnregisteredComponentException
	 */
	public Case get(String id) throws UnregisteredComponentException {
		
		Case result = null;
		
		for (Case c : Cases) {
			if (c.id() ==id)
			{
				result = c;
				break;
			}
		}
		
		return result;
	}

	/* (non-Javadoc)
	 * @see model.serialization.XmlSerializable#id()
	 */
	@Override
	public String id() {
		return Label;
	}

	
}
